package Java7_Concurrency_Cookbook.fork_join.recursive_action;

import java.util.List;
import java.util.concurrent.RecursiveAction;

/**
 * @author lixiangke
 * @date 2017/11/21
 */
public class Task extends RecursiveAction {
    private List<Product> products;
    private int first;
    private int last;
    private double increment;

    public Task(List<Product> products, int first, int last, double increment) {
        this.products = products;
        this.first = first;
        this.last = last;
        this.increment = increment;
    }

    @Override
    protected void compute() {
        if (last - first < 10) {
            updatePrices();
        } else {
            int middle = (last + first) / 2;
            // 已经提交到线程池且已开始执行的任务数
            System.out.printf("Zoom: Pending tasks: %s\n", getQueuedTaskCount());
            Task task1 = new Task(products, first, middle + 1, increment);
            Task task2 = new Task(products, middle + 1, last, increment);
            // 调用 invokeAll() 方法来执行主任务所创建的多个子任务.
            // 这是一个同步调用, 这个任务将等待子任务完成, 然后继续执行.
            // 当一个主任务等待他的子任务时, 执行这个主任务的工作者线程接收另一个等待执行的任务并开始执行
            // 正因为有了这个行为, 所以说Fork / Join 框架提供了一种比 Runnable 和 Callable 对象更加高效的任务管理机制
            invokeAll(task1, task2);
        }
    }

    private void updatePrices() {
        for (int i = first; i < last; i++) {
            Product product = products.get(i);
            product.setPrice(product.getPrice() * (1 + increment));
        }
    }
}
